package com.gitee.wsl.doc.prosemirror.transform.ext

import com.gitee.wsl.doc.prosemirror.model.content.NodeRange
import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
import com.gitee.wsl.doc.prosemirror.transform.TransformAble
import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceAroundStep


// Split the content in the given range off from its parent, if there is sibling content before
// or after it, and move it up the tree to the depth specified by `target`. You'll probably want
// to use [`liftTarget`](#transform.liftTarget) to compute `target`, to make sure the lift is
// valid.
fun<T: TransformAble> T.lift(range: NodeRange, target: Int) =apply {
    val tr = this
    val from = range.from
    val to = range.to
    val depth = range.depth

    val gapStart = from.before(depth + 1)
    val gapEnd = to.after(depth + 1)
    var start = gapStart
    var end = gapEnd

    var before = Fragment.empty
    var openStart = 0
    var splitting = false
    for (d in depth downTo target + 1) {
        if (splitting || from.index(d) > 0) {
            splitting = true
            before = Fragment.from(from.node(d).copy(before))
            openStart++
        } else {
            start--
        }
    }
    var after = Fragment.empty
    var openEnd = 0
    splitting = false
    for (d in depth downTo target + 1) {
        if (splitting || to.after(d + 1) < to.end(d)) {
            splitting = true
            after = Fragment.from(to.node(d).copy(after))
            openEnd++
        } else {
            end++
        }
    }

    tr.step(
        ReplaceAroundStep(
            from = start,
            to = end,
            gapFrom = gapStart,
            gapTo = gapEnd,
            slice = Slice(before.append(after), openStart, openEnd),
            insert = before.size - openStart,
            structure = true
        )
    )
}